use std::fs;
use std::path::Path;

/// 执行 cp 命令
pub fn execute(args: &[String]) {
    // 检查参数数量
    if args.len() != 2 {
        eprintln!("用法: cp <源文件/目录> <目标文件/目录>");
        return;
    }

    let source = &args[0];
    let target = &args[1];

    // 检查源路径是否存在
    let source_path = Path::new(source);
    if !source_path.exists() {
        eprintln!("错误: 源 '{}' 不存在", source);
        return;
    }

    // 判断源是文件还是目录
    if source_path.is_dir() {
        copy_directory(source_path, target);
    } else {
        copy_file(source_path, target);
    }
}

/// 复制文件
fn copy_file(source: &Path, target: &str) {
    let target_path = Path::new(target);

    // 检查目标是否已存在
    if target_path.exists() {
        eprintln!("错误: 目标 '{}' 已存在", target);
        return;
    }

    // 复制文件
    match fs::copy(source, target_path) {
        Ok(_) => println!("文件 '{}' 成功复制到 '{}'", source.display(), target),
        Err(e) => eprintln!("复制文件时出错: {}", e),
    }
}

/// 递归复制目录
fn copy_directory(source: &Path, target: &str) {
    let target_path = Path::new(target).join(source.file_name().unwrap()); // 目标目录下的文件名

    // 创建目标目录
    if let Err(e) = fs::create_dir_all(&target_path) {
        eprintln!("创建目标目录时出错: {}", e);
        return;
    }

    // 遍历源目录中的所有文件和子目录
    if let Ok(entries) = fs::read_dir(source) {
        for entry in entries {
            match entry {
                Ok(entry) => {
                    let entry_path = entry.path();
                    let target_entry_path = target_path.join(entry.file_name());

                    // 如果是目录，递归复制
                    if entry_path.is_dir() {
                        copy_directory(&entry_path, target_entry_path.to_str().unwrap());
                    } else {
                        copy_file(&entry_path, target_entry_path.to_str().unwrap());
                    }
                }
                Err(e) => eprintln!("读取目录时出错: {}", e),
            }
        }
    } else {
        eprintln!("读取源目录时出错: {}", source.display());
    }
}
